/**
 * 签到码路由
 * 处理签到码的生成、验证、查询、撤销等功能
 */

import { FastifyPluginAsync } from 'fastify'
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
import {
    GenerateSecretCodeSchema,
    GenerateSecretCodeResponseSchema,
    ValidateSecretCodeSchema,
    ValidateSecretCodeResponseSchema,
    GetActiveSecretCodeResponseSchema,
    RevokeSecretCodeResponseSchema
} from '../validators/secret-code.schema'
import {
    generateSecretCode,
    validateSecretCode,
    getActiveSecretCode,
    revokeSecretCode
} from '../services/secret-code.service'
import type { GenerateSecretCodeDTO, ValidateSecretCodeDTO } from '@services/common/types'

const secretCodeRoutes: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
    const server = fastify.withTypeProvider<TypeBoxTypeProvider>()

    /**
     * 生成签到码
     * POST /api/secret-code/generate
     */
    server.post(
        '/api/secret-code/generate',
        {
            schema: {
                description: '生成签到码（需要协管权限）',
                tags: ['签到码'],
                security: [{ bearerAuth: [] }],
                body: GenerateSecretCodeSchema,
                response: {
                    201: GenerateSecretCodeResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const body = request.body

            // 确保 generatedBy 与当前登录用户一致
            if (request.user && body.generatedBy !== request.user.userId) {
                throw new Error('您只能以自己的身份生成签到码')
            }

            // 转换 DTO
            const dto: GenerateSecretCodeDTO = {
                eventId: body.eventId!,
                generatedBy: body.generatedBy!,
                expiresIn: body.expiresIn
            }

            const result = await generateSecretCode(dto)

            if (!result.success) {
                throw new Error(result.message || '生成签到码失败')
            }

            // 转换 Date 为 ISO string
            const transformedData = {
                code: result.data!.code,
                eventId: result.data!.eventId,
                expiresAt: result.data!.expiresAt.toISOString(),
                generatedBy: result.data!.generatedBy
            }

            return reply.status(201).send({
                success: true,
                data: transformedData
            })
        }
    )

    /**
     * 验证签到码
     * POST /api/secret-code/validate
     */
    server.post(
        '/api/secret-code/validate',
        {
            schema: {
                description: '验证签到码是否有效',
                tags: ['签到码'],
                body: ValidateSecretCodeSchema,
                response: {
                    200: ValidateSecretCodeResponseSchema
                }
            }
        },
        async (request, reply) => {
            const body = request.body

            // 转换 DTO
            const dto: ValidateSecretCodeDTO = {
                eventId: body.eventId!,
                code: body.code!
            }

            const result = await validateSecretCode(dto)

            if (!result.success) {
                throw new Error(result.message || '验证签到码失败')
            }

            return reply.send({
                success: true,
                data: {
                    valid: result.data!,
                    message: result.message
                }
            })
        }
    )

    /**
     * 获取当前有效的签到码
     * GET /api/secret-code/active/:eventId
     */
    server.get(
        '/api/secret-code/active/:eventId',
        {
            schema: {
                description: '获取事件的当前有效签到码（需要协管权限）',
                tags: ['签到码'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        eventId: { type: 'string', format: 'uuid' }
                    },
                    required: ['eventId']
                },
                response: {
                    200: GetActiveSecretCodeResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const { eventId } = request.params as { eventId: string }
            const memberId = request.user!.userId

            const result = await getActiveSecretCode(eventId, memberId)

            if (!result.success) {
                throw new Error(result.message || '获取签到码失败')
            }

            // 转换 Date 为 ISO string
            const transformedData = result.data
                ? {
                      code: result.data.code,
                      eventId: result.data.eventId,
                      expiresAt: result.data.expiresAt.toISOString(),
                      generatedBy: result.data.generatedBy
                  }
                : null

            return reply.send({
                success: true,
                data: transformedData
            })
        }
    )

    /**
     * 撤销签到码
     * DELETE /api/secret-code/revoke/:eventId
     */
    server.delete(
        '/api/secret-code/revoke/:eventId',
        {
            schema: {
                description: '撤销事件的所有签到码（需要协管权限）',
                tags: ['签到码'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        eventId: { type: 'string', format: 'uuid' }
                    },
                    required: ['eventId']
                },
                response: {
                    200: RevokeSecretCodeResponseSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const { eventId } = request.params as { eventId: string }
            const memberId = request.user!.userId

            const result = await revokeSecretCode(eventId, memberId)

            if (!result.success) {
                throw new Error(result.message || '撤销签到码失败')
            }

            return reply.send({
                success: true,
                data: {
                    revoked: result.data!,
                    count: result.message?.match(/(\d+)/)?.[1] ? parseInt(result.message.match(/(\d+)/)![1]) : undefined
                }
            })
        }
    )
}

export default secretCodeRoutes

// fastify-autoload will use this exported 'prefix' when mounting the plugin
export const prefix = '/api/secret-code'
